package com.dcy.auth.biz.controller;

import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.dcy.auth.biz.dto.input.LoginInputDTO;
import com.dcy.auth.biz.dtomapper.MUserInfoMapper;
import com.dcy.auth.biz.service.AuthService;
import com.dcy.common.annotation.Log;
import com.dcy.common.annotation.LogEnum;
import com.dcy.common.constant.Constant;
import com.dcy.common.model.LoginAccount;
import com.dcy.common.model.R;
import com.dcy.common.model.ReturnCode;
import com.dcy.common.utils.BPwdEncoderUtil;
import com.dcy.db.base.controller.RBaseController;
import com.dcy.system.api.api.ADeptService;
import com.dcy.system.api.api.AUserService;
import com.dcy.system.api.constant.UserInfoStatusEnum;
import com.dcy.system.api.model.Role;
import com.dcy.system.api.model.UserInfo;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @author dcy
 * @Date: 2019/3/22 10:17
 * @Description:
 */
@RestController
@Api(tags = {"登录接口"})
@ApiSupport(order = 1)
@Slf4j
public class LoginController extends RBaseController {

    @Autowired
    private MUserInfoMapper mUserInfoMapper;

    @DubboReference(version = "1.0.0", check = false)
    private AUserService aUserService;
    @DubboReference(version = "1.0.0", check = false)
    private ADeptService aDeptService;
    @Autowired
    private AuthService authService;


    /**
     * 登录
     *
     * @param loginInputDTO
     * @return
     * @throws Exception
     */
    @Log(type = LogEnum.LOGIN)
    @PostMapping("/login")
    @ApiOperation(value = "用户登录")
    @ApiOperationSupport(order = 1,author = "dcy")
    public R<String> login(@Validated @ApiParam @RequestBody LoginInputDTO loginInputDTO) {
        // ----------------可以不调用------------------------
        UserInfo userInfo = aUserService.getUserInfoByUsername(loginInputDTO.getUsername());
        if (userInfo == null) {
            return R.error(ReturnCode.USER_PASSWORD_ERROR);
        }
        if (UserInfoStatusEnum.DISABLE.code.equals(userInfo.getUserStatus())) {
            return R.error(ReturnCode.USER_LOCKED_ERROR);
        }
        if (!BPwdEncoderUtil.matches(loginInputDTO.getPassword(), userInfo.getPassword().replace("{bcrypt}", ""))) {
            return R.error(ReturnCode.USER_PASSWORD_ERROR);
        }
        LoginAccount loginOutputDTO = mUserInfoMapper.toLoginAccount(userInfo);
        // 设置权限
        loginOutputDTO.setResources(authService.getAuthRoleAndResourceByUserId(userInfo.getId()));
        if (StrUtil.isNotBlank(userInfo.getDeptId())) {
            loginOutputDTO.setDeptName(aDeptService.getById(userInfo.getDeptId()).getName());
        }
        List<Role> authRoleListByUserId = aUserService.getAuthRoleListByUserId(userInfo.getId());
        if (CollUtil.isNotEmpty(authRoleListByUserId)) {
            loginOutputDTO.setRoleName(CollUtil.join(authRoleListByUserId.stream().map(Role::getRoleName).collect(Collectors.toList()), ","));
        }
        // sa-token 登录
        StpUtil.login(userInfo.getId());
        // 获取token
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
        // 获取session
        SaSession session = StpUtil.getSession();
        // 设置用户信息
        session.set(Constant.SESSION_USER_KEY, loginOutputDTO);
        return R.success(tokenInfo.getTokenValue());
    }

    @Log(type = LogEnum.BUSINESS)
    @GetMapping("/getUserInfo")
    @ApiOperation(value = "获取用户信息")
    @ApiOperationSupport(order = 5,author = "dcy")
    public R<LoginAccount> getUserInfo() {
        SaSession session = StpUtil.getSession();
        LoginAccount loginOutputDTO = session.getModel(Constant.SESSION_USER_KEY, LoginAccount.class);
        return R.success(loginOutputDTO);
    }

    @Log(type = LogEnum.LOGOUT)
    @PostMapping("/logout")
    @ApiOperation(value = "用户退出")
    @ApiOperationSupport(order = 10,author = "dcy")
    public R<String> logout() {
        StpUtil.logout();
        return R.success("退出成功");
    }
}
